﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using MacomberMapSystem.Common.Integration;
using MacomberMapSystem.Common.User_Interfaces.One_Lines;
using MacomberMapSystem.Common.CIM;

namespace MacomberMapSystem.Common.User_Interfaces.Mapping
{
    /// <summary>
    /// This class holds the information on the graphical representation of a substation
    /// </summary>
    public class MM_NetworkMap_Substation
    {
        #region Variable declarations
        /// <summary>The pixel coordinates for the substation at the current zoom level</summary>
        public Point SubXY;

        /// <summary>The substation upon which this element is based</summary>
        public MM_Substation BaseStation;

        /// <summary>The collection of element types in the substation</summary>
        public MM_OneLine_Element.enumElemTypes Elements = MM_OneLine_Element.enumElemTypes.Load;

        /// <summary>Whether the substation is currently visible on the map</summary>
        public bool Visible = false;

        /// <summary>Whether the substation has loads</summary>
        public bool HasLoad
        {
            get { return (Elements & MM_OneLine_Element.enumElemTypes.Load) == MM_OneLine_Element.enumElemTypes.Load; }
        }

        /// <summary>Whether the substation has generation</summary>
        public bool HasGen
        {
            get { return (Elements & MM_OneLine_Element.enumElemTypes.Unit) == MM_OneLine_Element.enumElemTypes.Unit; }
        }

        /// <summary>The CIM element associated with the substation</summary>
        public CIM_Element BaseElement;
        #endregion

        #region Initialization
        /// <summary>
        /// Initialize a new network map substation
        /// </summary>
        /// <param name="BaseStation"></param>
        /// <param name="Coordinates"></param>
        /// <param name="BaseElement"></param>        
        public MM_NetworkMap_Substation(MM_Substation BaseStation, CIM_Element BaseElement, MM_NetworkMap_Display Coordinates)
        {
            this.BaseStation = BaseStation;
            this.BaseElement = BaseElement;
            RecomputeSubstation(Coordinates);  
            if (BaseElement != null)          
                Elements = BaseElement.ElementTypes;

        }
        #endregion

        #region Lat/Long to pixel conversions
        /// <summary>
        /// Recompue a substation's position based on our coordinates
        /// </summary>
        /// <param name="Coordinates"></param>
        public void RecomputeSubstation(MM_NetworkMap_Display Coordinates)
        {
            this.SubXY = MM_NetworkMap_Display.LatLngToXY(BaseStation.LatLong, Coordinates.ZoomLevel);
        }
        #endregion

        #region Map interfacing
        /// <summary>
        /// Determine if a pixel is within 3 pixels of a substation's X/Y
        /// </summary>
        /// <param name="PixelXY"></param>
        /// <returns></returns>
        public bool HitTest(Point PixelXY)
        {
            Point DeltaPoint = new Point(PixelXY.X - SubXY.X, PixelXY.Y - SubXY.Y);
            if (Math.Abs(DeltaPoint.X) > 3 || Math.Abs(DeltaPoint.Y) > 3)
                return false;
            else
                return true;
        }
        #endregion

        #region Substation drawing
        /// <summary>
        /// Draw our substation on a network map
        /// </summary>
        /// <param name="g">The graphics connector</param>
        /// <param name="DisplayOptions">The display options for the map</param>        
        public void DrawSubstation(Graphics g, MM_NetworkMap_Display DisplayOptions)
        {
            //Determine our target lat/long, and our color
            Point SubstationCenter = MM_NetworkMap_Display.LatLngToXY(BaseStation.LatLong, DisplayOptions.ZoomLevel);
            Brush ForeBrush = new SolidBrush(HasLoad ? DisplayOptions.LoadColor : DisplayOptions.StationColor);
            ForeBrush = this.BaseStation.InDatabase ? Brushes.DarkBlue : Brushes.Red;
            //Draw the gen diamond or other square
            if (HasGen && DisplayOptions.GenerationDiamond)
                g.FillPolygon(ForeBrush, new PointF[] { new PointF(SubstationCenter.X - (DisplayOptions.StationSize * 2f), SubstationCenter.Y), new PointF(SubstationCenter.X, SubstationCenter.Y - (DisplayOptions.StationSize * 2f)), new PointF(SubstationCenter.X + (DisplayOptions.StationSize * 2f), SubstationCenter.Y), new PointF(SubstationCenter.X, SubstationCenter.Y + (DisplayOptions.StationSize * 2f)) });
            else
                g.FillRectangle(ForeBrush, SubstationCenter.X - DisplayOptions.StationSize, SubstationCenter.Y - DisplayOptions.StationSize, DisplayOptions.StationSize * 2f, DisplayOptions.StationSize * 2f);


            //Check to see if we're at the appropriate zoom levels, and draw the text
            if (DisplayOptions.ZoomLevel >= DisplayOptions.StationMWLevel || DisplayOptions.ZoomLevel >= DisplayOptions.StationNameLevel)
                g.DrawString(MapText(DisplayOptions), DisplayOptions.SubstationFont, Brushes.White, SubstationCenter.X + DisplayOptions.StationSize, SubstationCenter.Y + DisplayOptions.StationSize);
        }


        /// <summary>
        /// Return the appropriate text for the substation, as requested
        /// </summary>        
        /// <param name="DisplayOptions">The display options driving the network map</param>
        /// <returns></returns>
        public string MapText(MM_NetworkMap_Display DisplayOptions)
        {
            StringBuilder OutStr = new StringBuilder();
            if (DisplayOptions.ZoomLevel >= DisplayOptions.StationNameLevel)
                OutStr.Append(BaseStation.LongName);


            if ((DisplayOptions.ZoomLevel < DisplayOptions.StationMWLevel) || (!HasGen && !HasLoad))                
                return OutStr.ToString();
            if (DisplayOptions.ShowTotalLoad && HasLoad)
            {
                float TotalLoad = 0f;
                //TODO: Retrieve the substation's loads
                //foreach (MM_Load Load in Loads)
                //    TotalLoad += Load.MW_Est;
                OutStr.Append("\nLoad: " + TotalLoad.ToString("#,##0"));
            }
            if (HasGen)
            {
                float TotalGen = 0f, TotalHSL = 0f;
                //TODO: Retrieve the substation's units
                /*foreach (MM_Unit Unit in Units)
                {
                    
                    TotalGen += Unit.MW_Est;
                    TotalHSL += Unit.HSL;
                }
                */
                if (DisplayOptions.ShowTotalGeneration)
                    OutStr.Append("\nGen: " + TotalGen.ToString("#,##0"));
                if (DisplayOptions.ShowTotalHSL)
                    OutStr.Append("\nHSL: " + TotalHSL.ToString("#,##0"));
                if (DisplayOptions.ShowRemainingCapacity)
                    OutStr.Append("\nRem: " + (TotalHSL - TotalGen).ToString("#,##0"));
            }

            return OutStr.ToString();

        }
        #endregion
    }

}
